define(['jquery', 'template'], function ($, template) {


    function table(options) {

        var me = this;

        var defaults = this.defaults = {
            renderTo: '',
            url: '',
            ajaxType: 'post',
            fields: [],
            data: []
        };

        $.extend(defaults, options, {
            tpl: {
                table: '<div class="table">' +
                '<table>' +
                '<thead>' +
                '<tr>' +
                '<td colspan="{{fields.length}}"></td>' +
                '</tr>' +
                '<tr>' +
                '{{each fields as f}}' +
                '<th>{{f.title}}{{if f.sort}}<span data-field="{{f.name}}" data-type="{{f.type}}" class="table-sort"></span>{{/if}}</th>' +
                '{{/each}}' +
                '</tr>' +
                '</thead>' +
                '<tbody class="table-body">' +
                '{{#initBody}}' +
                '</tbody>' +
                '<tfoot><tr>' +
                '<td colspan="{{fields.length}}" class="table-foot"></td>' +
                '</tr></tfoot>' +
                '</table>' +
                '</div>',
                body: '{{each list as v i}}' +
                '<tr>' +
                '{{each fields as v1 i1}}' +
                '<td>{{v[v1.name]}}</td>' +
                '{{/each}}' +
                '</tr>' +
                '{{/each}}',
                page: '<ul class="page">' +
                '{{if page.start!=1}}' +
                '<li class="page-first"></li>' +
                '{{/if}}' +
                '{{if page.no!=1}}' +
                '<li class="page-prev"></li>' +
                '{{/if}}' +
                '{{each page.data as v}}' +
                '<li class="{{v.cls}}" data-no="{{v.no}}">{{v.no}}</li>' +
                '{{/each}}' +
                '{{if page.no!==page.count}}' +
                '<li class="page-next"></li>' +
                '{{/if}}' +
                '{{if page.end!==page.count}}' +
                '<li class="page-last"></li>' +
                '{{/if}}' +
                '</ul>'
            }
        });

        template.helper('initBody', function () {
            return template.compile(defaults.tpl.body)(me.renderData);
        });

        this.originData = null;

        this.page = {
            no: 1,
            size: 10,
            count: 22,
            data: [],
            start: 1,
            end: 10
        };


        this.renderData = {
            list: null,
            page: this.page,
            fields: me.defaults.fields
        };


        if (!defaults.url && defaults.data) {
            this.originData = defaults.data;
            this.renderData.list = defaults.data;
        }
        this.$renderTo = $(defaults.renderTo);
        this.$renderTo.on('click', '.table-sort', function () {
            var data = $(this).data();
            if (data.order == 'asc') {
                data.order = 'desc';
            } else {
                data.order = 'asc';
            }
            $(this).data('order', data.order);
            me.sort(data);
        });
        this.callback = null;

        this.sortType = {
            'date': function (a, b) {
                a = new Date(a[this.field]);
                b = new Date(b[this.field]);
                if (this.order == 'desc') {
                    return b - a;
                }
                return a - b;
            },
            'string': function (a, b) {
                if (this.order == 'desc') {
                    return a[this.field] < b[this.field] ? 1 : -1;
                }
                return a[this.field] > b[this.field] ? 1 : -1;
            }
        };
        this.init();
    }


    table.prototype = {
        constructor: table,

        _tpl2Html: function (tplName) {
            return template.compile(this.defaults.tpl[tplName])(this.renderData);
        },

        _renderBody: function () {
            this.$renderTo.find('.table-body').html(this._tpl2Html('body'));
        },

        _renderPage: function () {
            this.$renderTo.find('.table-foot').html(this._tpl2Html('page'));
        },

        _initPage: function () {
            var me = this;
            me._updatePage();

            this.$renderTo.on('click', '.page li', function () {
                var $li = $(this);
                if ($li.hasClass('page-no')) {
                    $li.addClass('active').siblings('li').removeClass('active');
                    var no = $li.data('no');
                    me.page.no = no;
                } else if ($li.hasClass('page-first')) {
                    me.page.no = 1;
                } else if ($li.hasClass('page-prev')) {
                    me.page.no--;
                    if (me.page.no < 1) {
                        me.page.no = 1;
                    }
                } else if ($li.hasClass('page-next')) {
                    me.page.no++;
                    if (me.page.no > me.page.count) {
                        me.page.no = me.page.count;
                    }
                } else if ($li.hasClass('page-last')) {
                    me.page.no = me.page.count;
                }
                me.callback = me._updatePage;
                me.getData();
            });

        },

        _updatePage: function () {
            this.page.data = [];
            if (this.page.no > this.page.count) {
                this.page.no = this.page.count;
            }

            if (this.page.count <= 10) {
                this.page.start = 1;
                this.page.end = this.page.count;
            } else {

                this.page.start = this.page.no - 5;
                this.page.end = this.page.no + 4;

                if (this.page.start < 1) {
                    this.page.start = 1;
                    this.page.end = 10
                }
                if (this.page.end > this.page.count) {
                    this.page.start = this.page.count - 9;
                    this.page.end = this.page.count;
                }
            }

            for (var i = this.page.start; i <= this.page.end; i++) {
                this.page.data.push({
                    no: i,
                    cls: 'page-no'
                });
            }

            this.page.data[this.page.no - this.page.start].cls += ' active';

            this._renderBody();
            this._renderPage();
        },

        init: function () {
            if (this.originData) {
                this.$renderTo.html(this._tpl2Html('table'));
                this._initPage();
            } else {
                this.callback = this.init;
                this.getData();
            }
        },

        sort: function (data) {
            var sortFn = this.sortType[data.type].bind(data);
            this.renderData.list.sort(sortFn);
            this._renderBody();
        },

        getData: function () {
            var me = this;
            $.ajax({
                url: this.defaults.url,
                type: this.defaults.ajaxType,
                cache: false,
                dataType: 'json',
                success: function (data) {
                    me.originData = data.dataList;
                    me.renderData.list = data.dataList;
                    me.page.count = Math.ceil(data.totalCount / me.page.size);
                    me.callback();
                },
                error: function () {
                }
            });
        }
    };

    return function factory(options) {
        return new table(options);
    }

});